package org.xiaov.rabbitmq.config;

import cn.hutool.json.JSONUtil;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.xiaov.common.bean.rabbitmq.DelayQueueInfo;
import org.xiaov.common.bean.rabbitmq.QueueChain;
import org.xiaov.common.bean.rabbitmq.QueueGroup;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xiaovcloud
 * @since 2021/10/29 10:48
 */
@Configuration
public class DelayConfig {

    @Value("${v.rabbitmq.dead.exchange}")
    private String deadExchange;
    @Value("${v.rabbitmq.dead.queue}")
    private String deadQueue;
    @Value("${v.rabbitmq.dead.key}")
    private String deadRoutingKey;


    @Value("${v.rabbitmq.delay.queues}")
    private String delayQueueListStr;
    @Value("${v.rabbitmq.delay.exchange}")
    private String delayExchange;

    /**
     * 最后发送到邮件队列
     */
    @Value("${v.rabbitmq.email.queue}")
    private String emailQueueName;
    @Value("${v.rabbitmq.email.exchange}")
    private String emailExchangeName;
    @Value("${v.rabbitmq.email.key}")
    private String emailRoutingKey;

    @Resource
    RabbitAdmin rabbitAdmin;

    /**
     * 死信交换机
     *
     * @return deadExchange
     */
    @Bean
    public DirectExchange deadExchange() {
        return new DirectExchange(deadExchange);
    }

    /**
     * 死信队列
     *
     * @return Queue
     */
    @Bean
    public Queue deadQueue() {
        return new Queue(deadQueue);
    }

    /**
     * 死信绑定
     *
     * @return Binding
     */
    @Bean
    public Binding bindingDead() {
        return BindingBuilder.bind(deadQueue()).to(deadExchange()).with(deadRoutingKey);
    }


    /**
     * 延时交换机
     *
     * @return DirectExchange
     */
    @Bean
    public DirectExchange delayExchange() {
        return new DirectExchange(delayExchange);
    }

    /**
     * 延时队列
     *
     * @return QueueChain
     */
    @Bean
    public QueueChain createQueueChain() {
        List<DelayQueueInfo> queueInfoList = JSONUtil.toList(delayQueueListStr, DelayQueueInfo.class);

        //
        rabbitAdmin.declareExchange(deadExchange());
        rabbitAdmin.declareQueue(deadQueue());
        rabbitAdmin.declareBinding(bindingDead());
        rabbitAdmin.declareExchange(delayExchange());

        //创建3个队列
        for (DelayQueueInfo delayQueueInfo : queueInfoList) {
            Map<String, Object> args = new HashMap<>(3);
            //声明死信交换器
            args.put("x-dead-letter-exchange", deadExchange);
            //声明死信路由键
            args.put("x-dead-letter-routing-key", deadRoutingKey);
            //声明队列消息过期时间
            args.put("x-message-ttl", delayQueueInfo.getExpireTime());
            //队列持久
            Queue queue = new Queue(delayQueueInfo.getDelayQueueName(), true, false, true, args);
            rabbitAdmin.declareQueue(queue);

            Binding binding = BindingBuilder.bind(queue).to(delayExchange()).with(delayQueueInfo.getRouteKey());
            rabbitAdmin.declareBinding(binding);
        }

        QueueChain queueChain = new QueueChain();
        for (int i = 0; i < queueInfoList.size(); i++) {
            DelayQueueInfo delayQueueInfo = queueInfoList.get(i);
            if (i == 0) {
                queueChain.setFirstQueue(new QueueGroup(delayQueueInfo.getDelayQueueName(), delayExchange, delayQueueInfo.getRouteKey()));
            }
            // 拿到下一个queueName
            if (i < queueInfoList.size() - 1) {
                int nextIndex = i + 1;
                DelayQueueInfo nexDelayQueueInfo = queueInfoList.get(nextIndex);
                if (nexDelayQueueInfo != null) {
                    queueChain.addQueue(delayQueueInfo.getDelayQueueName(), new QueueGroup(nexDelayQueueInfo.getDelayQueueName(), delayExchange, nexDelayQueueInfo.getRouteKey()));
                }
            }
            if (i == queueInfoList.size() - 1) {
                //当运行到最后的队列时发到mail的队列去
                queueChain.addQueue(delayQueueInfo.getDelayQueueName(), new QueueGroup(emailQueueName, emailExchangeName, emailRoutingKey));

                //生成email的队列
                DirectExchange emailExchange = new DirectExchange(emailExchangeName);
                Queue emailQueue = new Queue(emailQueueName);
                Binding emailBinding = BindingBuilder.bind(emailQueue).to(emailExchange).with(emailRoutingKey);
                rabbitAdmin.declareExchange(emailExchange);
                rabbitAdmin.declareQueue(emailQueue);
                rabbitAdmin.declareBinding(emailBinding);
            }
        }
        return queueChain;
    }
}
